﻿using Inventor;
using System;
using System.Collections.Generic;
using System.IO;
using File = System.IO.File;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using AutodeskInventorInterfaces.Model;
using AutodeskInventorInterfaces.Model.Exceptions;
using System.Collections.Concurrent;
using AutodeskInventorInterfaces.Model.Translators;
using System.Timers;
using System.Reflection;
using System.Xml.Linq;
using System.Linq;
using System.Collections;
using AutodeskInventorInterfaces.Extend;

namespace AutodeskInventorInterfaces.Service
{
  public class InventorApplication
  {
    private static Application application = null;
    /// <summary>
    /// 获取当前可用的Inventor Application实例
    /// </summary>
    public static Application Application
    {
      get
      {
        try
        {
          if (application != null && application.Ready)
          {
            application.WindowState = WindowsSizeEnum.kMaximize;
            application.Visible = true;
            return application;
          }
        }
        catch { }
        try
        {
          //查找可用实例
          application = Marshal.GetActiveObject("Inventor.Application") as Application;
          Log("Find Exists Inventor Application Success With Marshal.GetActiveObject Method.");
        }
        catch (Exception ex)
        {
          Error($"Find Exists Inventor Application Failed! {ex.Message}");
          try
          {
            //创建新实例
            var inventorAppType = Type.GetTypeFromProgID("Inventor.Application");
            application = Activator.CreateInstance(inventorAppType) as Application;
            Log("Create New Inventor Application Success With Type.GetTypeFromProgID Method.");
          }
          catch (Exception innerEx)
          {
            Error($"Create New Inventor Application Initialize Failed! {innerEx.Message}");
            Process.GetCurrentProcess().Close();
          }
        }
        finally
        {
          if (application != null)
          {
            application.ApplicationEvents.OnQuit += ApplicationEvents_OnQuit;
            application.WindowState = WindowsSizeEnum.kMaximize;
            application.Visible = true;
            application.SilentOperation = true;
          }
        }
        return application;
      }
    }

    private static void ApplicationEvents_OnQuit(EventTimingEnum BeforeOrAfter, NameValueMap Context, out HandlingCodeEnum HandlingCode)
    {
      application.ApplicationEvents.OnQuit -= ApplicationEvents_OnQuit;
      HandlingCode = HandlingCodeEnum.kEventHandled;
      application = null;
    }

    /// <summary>
    /// 零部件列表内存缓存
    /// </summary>
    private static IList<string> PartFiles { get; set; }

    /// <summary>
    /// 
    /// </summary>
    private static string LogFilePath
    {
      get
      {
        return $"{AppContext.BaseDirectory}logs\\og_{DateTime.Now:yyyy-MM-dd}.log";
      }
    }

    /// <summary>
    /// 
    /// </summary>
    private static string ErrorFilePath
    {
      get
      {
        return $"{AppContext.BaseDirectory}logs\\error_{DateTime.Now:yyyy-MM-dd}.log";
      }
    }

    /// <summary>
    /// 
    /// </summary>
    public static string PartTempPath
    {
      get
      {
        return $"{AppContext.BaseDirectory}Parts\\{DateTime.Now:yyyy}\\{DateTime.Now:yyyy-MM-dd}\\";
      }
    }

    public static string ClonePartsPath
    {
      get
      {
        return $"{AppContext.BaseDirectory}CloneParts\\{DateTime.Now:yyyy}\\{DateTime.Now:yyyy-MM-dd}\\";

      }
    }

    /// <summary>
    /// 释放资源
    /// </summary>
    public static void Release()
    {
      Log("Inventor Application Closed.");
    }

    /// <summary>
    /// 记录日志
    /// </summary>
    /// <param name="log"></param>
    public static void Log(string log)
    {
      File.AppendAllText(LogFilePath, $"[{DateTime.Now}] {log}\r\n");
    }

    /// <summary>
    /// 记录错误日志
    /// </summary>
    /// <param name="error"></param>
    public static void Error(string error)
    {
      File.AppendAllText(ErrorFilePath, $"[{DateTime.Now}] {error}\r\n");
    }

    /// <summary>
    /// 记录错误对象的日志
    /// </summary>
    /// <param name="exc"></param>
    public static void Error(Exception exc)
    {
      Error(exc.Message);
    }

    /// <summary>
    /// 获取零部件文件列表
    /// </summary>
    /// <returns></returns>
    public static IList<string> GetPartFiles()
    {
      var partPath = $"{AppContext.BaseDirectory}Parts\\";

      return new List<string>(Directory.GetFiles(partPath, "*.*", SearchOption.TopDirectoryOnly).Where(name =>
      {
        return name.EndsWith(".ipt", StringComparison.OrdinalIgnoreCase)
          || name.EndsWith(".iam", StringComparison.OrdinalIgnoreCase)
          || name.EndsWith(".idw", StringComparison.OrdinalIgnoreCase)
          || name.EndsWith(".ipj", StringComparison.OrdinalIgnoreCase);
      }));
    }

    /// <summary>
    /// 克隆指定路径的文件
    /// </summary>
    /// <param name="sourceFile"></param>
    /// <param name="destPath">克隆后存放的目的文件夹</param>
    /// <returns></returns>
    public static string CloneFile(string sourceFile, string destPath = null)
    {
      var sourceFileInfo = new FileInfo(sourceFile);
      if (destPath.IsNullOrEmpty())
      {
        destPath = $"{PartTempPath}{Guid.NewGuid()}\\";
      }
      var newPartFile = $"{destPath}{sourceFileInfo.Name}";
      try
      {
        var fileInfo = new FileInfo(newPartFile);
        if (!fileInfo.Directory.Exists)
        {
          Directory.CreateDirectory(fileInfo.Directory.FullName);
        }
        File.Copy(sourceFile, newPartFile, true);
        return newPartFile.ToRelativePath();
      }
      catch (Exception ex)
      {
        throw InventorException.文档克隆失败.Create(sourceFile).SetDetail(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
      }
    }

    /// <summary>
    /// 克隆指定路径的装配模板，会同时克隆引用的零部件
    /// </summary>
    /// <param name="templateAssFile"></param>
    /// <param name="destPath"></param>
    /// <returns></returns>
    public static object CloneAssemblyDocument(string templateAssFile, string destPath = null)
    {
      var server = new ApprenticeServerComponent();
      var templateAssFileInfo = new FileInfo(templateAssFile);
      if (destPath.IsNullOrEmpty())
      {
        destPath = $"{ClonePartsPath}{Guid.NewGuid()}\\";
      }
      var newAssFile = $"{destPath}{templateAssFileInfo.Name}";
      if (!Directory.Exists(destPath))
      {
        Directory.CreateDirectory(destPath);
      }
      var refFiles = new List<String>();
      var assDoc = server.Open(templateAssFile);
        var fileSaveAs = server.FileSaveAs;
      fileSaveAs.AddFileToSave(assDoc, newAssFile);
      foreach (ApprenticeServerDocument doc in assDoc.AllReferencedDocuments)
      {
        var refFile = new FileInfo(doc.FullFileName);
        var newRefFile = $"{destPath}clone_{refFile.Name}";
        fileSaveAs.AddFileToSave(doc, newRefFile);
        refFiles.Add(newRefFile.ToRelativePath());
      }
      fileSaveAs.ExecuteSaveCopyAs();
      assDoc.Close();
      server.Close();
      return new
      {
        AssFile = newAssFile.ToRelativePath(),
        RefFiles = refFiles
      };
    }

    /// <summary>
    /// 克隆指定路径的装配模板，会同时克隆引用的零部件
    /// </summary>
    /// <param name="templateAssFile"></param>
    /// <returns></returns>
    public static object CloneAssemblyDocument_Old(string templateAssFile, string destPath = null)
    {
      try
      {
        var templateAssFileInfo = new FileInfo(templateAssFile);
        if (destPath.IsNullOrEmpty())
        {
          destPath = $"{ClonePartsPath}{Guid.NewGuid()}\\";
        }
        var newAssFile = $"{destPath}{templateAssFileInfo.Name}";
        if (!Directory.Exists(destPath))
        {
          Directory.CreateDirectory(destPath);
        }
        // File.Copy(templateAssFile, newAssFile, true);// 复制装配文件到新文件夹
        var refFiles = new List<String>();
        var assDoc = OpenDocument<AssemblyDocument>(templateAssFile);
        foreach (Inventor.File file in assDoc.File.AllReferencedFiles)
        {
          var refFile = new FileInfo(file.FullFileName);
          var newRefFile = $"{destPath}{refFile.Name}";
          //File.Copy(file.FullFileName, newRefFile, true);
          var doc = OpenDocument(file.FullFileName);
          // doc.FullFileName = newRefFile;
          doc.SaveAs(newRefFile, true);
          doc.Close(true);

          refFiles.Add(newRefFile.ToRelativePath());
        }

        assDoc.SaveAs(newAssFile, true);
        assDoc.Close(true);
        assDoc = OpenDocument<AssemblyDocument>(newAssFile);
        assDoc.Update2(true);
        assDoc.Rebuild2(true);
        assDoc.Save2(true);
        return new
        {
          AssFile = newAssFile.ToRelativePath(),
          RefFiles = refFiles
        };
      }
      catch (Exception ex)
      {
        throw InventorException.文档克隆失败.Create(templateAssFile).SetDetail(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
      }
    }

    /// <summary>
    /// 获取指定装配文件的所有关联文件
    /// </summary>
    /// <param name="assFile"></param>
    /// <returns></returns>
    public static IList<String> GetAssemblyReferencedFiles(string assFile)
    {
      var refFiles = new List<String>();
      var assDoc = OpenDocument<AssemblyDocument>(assFile);
      foreach (Inventor.File file in assDoc.File.AllReferencedFiles)
      {
        refFiles.Add(file.FullFileName.ToRelativePath());
      }
      return refFiles;
    }

    //public static bool PackageFiles(string templateAssFile, IList<String> files) { }

    /// <summary>
    /// 打开零部件文档，返回指定T类型
    /// </summary>
    /// <returns></returns>
    public static T OpenDocument<T>(string partFile)
    {
      if (!File.Exists(partFile))
      {
        throw InventorException.文档未找到;
      }
      try
      {
        var app = Application;
        // 如果120s都未打开成功，则执行超时操作
        var timer = new Timer(120 * 1000);
        timer.Elapsed += (sender, e) =>
        {
          app.Quit();
          timer.Dispose();
          timer = null;
        };

        var partDoc = app.Documents.Open(partFile, true);
        if (timer != null)
        {
          timer.Stop();
          timer.Dispose();
        }

        Log($"Open Part File '{partFile}' Successd.");

        return (T)partDoc;
      }
      catch (Exception exc)
      {
        throw InventorException.文档打开失败.Create(partFile).SetDetail(exc.Message);
      }
    }

    /// <summary>
    /// 打开零部件文档
    /// </summary>
    /// <param name="partFile"></param>
    /// <returns></returns>
    public static dynamic OpenDocument(string partFile)
    {
      return OpenDocument<dynamic>(partFile);
    }

    /// <summary>
    /// 关闭指定的零部件文档
    /// </summary>
    /// <param name="partFile"></param>
    public static void CloseDocument(string partFile)
    {
      try
      {
        dynamic partDoc = Application.Documents.ItemByName[partFile];
        try
        {
          partDoc.Close(true);
          partDoc = null;
          Log($"Close Document '{partFile}' Successd.");
        }
        catch (Exception exc)
        {
          throw InventorException.文档关闭失败.Create(partFile).SetDetail(exc.Message);
        }
      }
      catch
      {
        throw InventorException.对象未找到.Create(partFile.ToRelativePath());
      }
    }

    /// <summary>
    /// 关闭所有已打开的文档
    /// </summary>
    public static void CloseAllDocuments()
    {
      foreach(dynamic doc in Application.Documents)
      {
        try
        {
          doc.Close(true);
        }
        catch { }
      }
      Log($"Close All Documents Successd.");

    }

    /// <summary>
    /// 移除零部件模板
    /// </summary>
    /// <param name="partFile"></param>
    /// <returns></returns>
    public static bool RemoveTemplatePartFile(string partFile)
    {
      CloseDocument(partFile);
      try
      {
        if (File.Exists(partFile))
        {
          File.Delete(partFile);
        }
        return true;
      }
      catch (Exception ex)
      {
        throw InventorException.模板文档移除失败.Create(partFile).SetDetail(ex.Message);
      }
    }

    /// <summary>
    /// 获取指定零部件文件的组件参数
    /// </summary>
    /// <param name="partFile"></param>
    /// <returns></returns>
    public static IDictionary<String, IList<Parameter>> GetParameters(string partFile)
    {
      var partDoc = OpenDocument(partFile);
      return GetParameters<Parameter>(partDoc);
    }

    /// <summary>
    /// 获取指定零部件文件的组件参数
    /// </summary>
    /// <param name="partFile"></param>
    /// <returns></returns>
    public static IDictionary<String, IList<T>> GetParameters<T>(string partFile, Func<Parameter, T> handler = null)
    {
      var partDoc = OpenDocument(partFile);
      return GetParameters<T>(partDoc, handler);
    }

    /// <summary>
    /// 获取指定零部件的组件参数
    /// </summary>
    /// <param name="partDoc"></param>
    /// <returns></returns>
    public static IDictionary<String, IList<T>> GetParameters<T>(dynamic partDoc, Func<Parameter, T> handler = null)
    {
      var groups = new Dictionary<String, IList<T>>();
      groups[(partDoc.FullFileName as string).ToRelativePath()] = GetDocumentParameters(partDoc, handler); // 获取根文档的参数
      // 获取所有关联文档的参数
      var docs = partDoc.AllReferencedDocuments;
      foreach (dynamic doc in docs)
      {
        var parameters = GetDocumentParameters(doc, handler);
        groups[(doc.File.FullFileName as string).ToRelativePath()] = parameters;
      }
      return groups;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="doc"></param>
    /// <param name="handler"></param>
    /// <returns></returns>
    public static IList<T> GetDocumentParameters<T>(dynamic doc, Func<Parameter, T> handler = null)
    {
      var parameters = new List<T>();
      foreach (Parameter p in doc.ComponentDefinition.Parameters)
      {
        if (handler != null)
        {
          parameters.Add(handler(p));
        }
        else
        {
          parameters.Add((T)p);
        }
      }
      return parameters;
    }

    /// <summary>
    /// 获取零部件文件的螺纹特征数据
    /// 
    /// </summary>
    /// <param name="partFile">零部件文件路径</param>
    /// <returns></returns>
    public static IList<ClientDocumentHoleFeatures> GetClientHoleFeatures(string partFile, string holeName = null)
    {
      var partDoc = OpenDocument(partFile);
      return GetClientHoleFeatures(partDoc);
    }

    /// <summary>
    /// 获取零部件文件的螺纹特征数据
    /// </summary>
    /// <param name="partDoc"></param>
    /// <param name="holeName"></param>
    /// <returns></returns>
    public static IList<ClientDocumentHoleFeatures> GetClientHoleFeatures(dynamic partDoc, string holeName = null)
    {
      var allDocHoleFeatures = new List<ClientDocumentHoleFeatures>();
      var rootDocHoleFeatures = GetDocumentClientHoleFeatures(partDoc, holeName);
      allDocHoleFeatures.Add(rootDocHoleFeatures);

      // 获取所有关联文档的孔特征参数
      var docs = partDoc.AllReferencedDocuments;
      foreach (dynamic doc in docs)
      {
        var holeFeatuers = GetDocumentClientHoleFeatures(doc);
        allDocHoleFeatures.Add(holeFeatuers);
      }
      return allDocHoleFeatures;
    }

    /// <summary>
    /// 获取零部件文件的螺纹特征数据
    /// </summary>
    /// <returns></returns>
    public static ClientDocumentHoleFeatures GetDocumentClientHoleFeatures(dynamic rootDoc, string holeName = null, dynamic aaa = null)
    {
      var holeFeatures = GetDocumentHoleFeatures(rootDoc, holeName);
      return new ClientDocumentHoleFeatures
      {
        Template = (rootDoc.FullFileName as string).ToRelativePath(),
        HoleFeatures = (List<ClientHoleFeature>)(holeFeatures as IList<HoleFeature>).Map(holeFeature => holeFeature.ToClientFeature())
      };
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="partDoc"></param>
    /// <param name="holeName"></param>
    /// <returns></returns>
    public static IList<HoleFeature> GetDocumentHoleFeatures(dynamic partDoc, string holeName = null)
    {
      var holeFeatures = new List<HoleFeature>();
      var features = partDoc.ComponentDefinition.Features;
      var findHole = !string.IsNullOrEmpty(holeName); // 是否需要根据名称查找指定的孔
      foreach (HoleFeature feature in features.HoleFeatures)
      {
        if (findHole)
        {
          if (feature.Name != holeName)
          {
            continue;
          }
          else
          {
            holeFeatures.Add(feature);// 找到孔之后退出循环
            break;
          }
        }
        else
        {
          holeFeatures.Add(feature);
        }
      }
      return holeFeatures;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="partDoc"></param>
    /// <returns></returns>
    public static IDictionary<string, dynamic> GetAllDocument(dynamic partDoc)
    {
      var allDocs = new Dictionary<string, dynamic>();
      allDocs[(partDoc.FullFileName as string).ToRelativePath()] = partDoc;
      foreach (dynamic doc in partDoc.AllReferencedDocuments)
      {
        allDocs[(doc.FullFileName as string).ToRelativePath()] = doc;
      }
      return allDocs;
    }

    /// <summary>
    /// 设置指定零部件的参数
    /// </summary>
    /// <param name="partDoc">文档对象</param>
    /// <param name="parameters">参数集合</param>
    /// <param name="saveDoc">是否保存文档</param>
    public static dynamic SetParameters(dynamic partDoc, IList<ClientDocumentParameter> documentsParameters)
    {
      try
      {
        var allDocs = GetAllDocument(partDoc);
        foreach (var docParameters in documentsParameters)
        {
          var docFileName = docParameters.Template.ToLower();
          if (allDocs.TryGetValue(docFileName, out dynamic doc))
          {
            SetDocumentParameters(doc, docParameters.Parameters);
          }
        }
        partDoc.Update2(true);
        partDoc.Save2(true);
        return partDoc;
      }
      catch (Exception exc)
      {
        throw InventorException.参数设置失败.Create((string)partDoc.FullFileName).SetDetail(exc.Message);
      }
    }

    /// <summary>
    /// 设置指定零部件的参数
    /// </summary>
    /// <param name="partDoc">文档对象</param>
    /// <param name="parameters">参数集合</param>
    /// <param name="saveDoc">是否保存文档</param>
    public static void SetDocumentParameters(dynamic partDoc, IList<ClientParameter> parameters)
    {
      try
      {
        foreach (var cp in parameters)
        {
          var p = partDoc.ComponentDefinition.Parameters[cp.Name];
          if (p == null)
          {
            partDoc.ComponentDefinition.Parameters.UserParameters.AddByValue(cp.Name, cp.Value, cp.Units);
          }
          else
          {
            p.Value = cp.Value;
            if (!string.IsNullOrEmpty(cp.Units) && p.Units != cp.Units)
            {
              p.Units = cp.Units;
            }
          }
        }
        partDoc.Update2(true);
        partDoc.Save2(true);
      }
      catch (Exception exc)
      {
        throw InventorException.参数设置失败.Create((string)partDoc.FullFileName).SetDetail(exc.Message);
      }
    }

    /// <summary>
    /// 设置指定零部件文档的参数
    /// </summary>
    /// <param name="partFile"></param>
    /// <param name="parameters"></param>
    public static dynamic SetParameters(string partFile, IList<ClientParameter> parameters)
    {
      var partDoc = OpenDocument(partFile);
      if (partDoc == null)
      {
        return null;
      }
      return SetParameters(partDoc, parameters);
    }

    /// <summary>
    /// 设置零部件指定孔的特征参数
    /// </summary>
    /// <param name="partDoc"></param>
    /// <param name="clientHoleFeatures"></param>
    /// <returns></returns>
    public static dynamic SetDocumentHoleFeatures(dynamic partDoc, List<ClientHoleFeature> clientHoleFeatures)
    {
      foreach (var holeParams in clientHoleFeatures)
      {
        var holeFeatures = GetDocumentHoleFeatures(partDoc, holeParams.Name);
        if (holeFeatures == null || holeFeatures.Count == 0)
        {
          throw InventorException.对象未找到.Create(holeParams.Name);
        }
        var holeFeature = holeFeatures[0];
        if (holeParams.BottomTipAngle != null)
        {
          // 设置孔底参数
          holeFeature.BottomTipAngle.Value = holeParams.BottomTipAngle.Value;
        }
        var clientTapInfo = holeParams.TapInfo;
        if (holeParams.TapInfo != null)
        {
          // 设置孔螺纹特征参数
          var holeTapInfo = holeFeature.TapInfo as HoleTapInfo;
          if (holeTapInfo == null)
          {
            throw InventorException.对象未找到.Create($"{holeParams.Name}特征参数");
          }

          // 设置【螺纹类型】
          if (clientTapInfo.ThreadType.IsNotNullOrEmpty())
          {
            holeTapInfo.ThreadType = clientTapInfo.ThreadType;
          }

          // 设置【螺纹类别】
          if (clientTapInfo.Class.IsNotNullOrEmpty())
          {
            holeTapInfo.Class = clientTapInfo.Class;
          }

          // 设置是否【全螺纹】
          if (clientTapInfo.FullThreadDepth != null)
          {
            holeTapInfo.FullTapDepth = clientTapInfo.FullThreadDepth.Value;
          }

          /*************************************设置【螺纹尺寸】 Begin*************************************/
          // MajorDiameter
          if (clientTapInfo.MajorDiameterMin != null)
          {
            holeTapInfo.MajorDiameterMin = clientTapInfo.MajorDiameterMin;
          }
          if (clientTapInfo.MajorDiameterMax != null)
          {
            holeTapInfo.MajorDiameterMax = clientTapInfo.MajorDiameterMax;
          }

          // MinorDiameter
          if (clientTapInfo.MinorDiameterMin != null)
          {
            holeTapInfo.MinorDiameterMin = clientTapInfo.MinorDiameterMin;
          }
          if (clientTapInfo.MinorDiameterMax != null)
          {
            holeTapInfo.MinorDiameterMax = clientTapInfo.MinorDiameterMax;
          }

          // PitchDiameter
          if (clientTapInfo.PitchDiameterMin != null)
          {
            holeTapInfo.PitchDiameterMin = clientTapInfo.PitchDiameterMin;
          }
          if (clientTapInfo.PitchDiameterMax != null)
          {
            holeTapInfo.PitchDiameterMax = clientTapInfo.PitchDiameterMax;
          }
          /*************************************设置【螺纹尺寸】 End*************************************/
        }
      }

      partDoc.Update();
      partDoc.Save();
      return partDoc;
    }

    /// <summary>
    /// 设置零部件文件指定孔的特征参数
    /// </summary>
    /// <param name="partFile"></param>
    /// <param name="parameters"></param>
    public static dynamic SetHoleFeatures(string partFile, List<ClientDocumentHoleFeatures> clientDocumentHoleFeatures)
    {
      var partDoc = OpenDocument(partFile);
      if (partDoc == null)
      {
        return null;
      }
      var allDocs = GetAllDocument(partDoc);
      foreach (var clientDocumentHoleFeature in clientDocumentHoleFeatures)
      {
        var docFileName = clientDocumentHoleFeature.Template.ToLower();
        if (allDocs.TryGetValue(docFileName, out dynamic doc))
        {
          SetDocumentHoleFeatures(doc, clientDocumentHoleFeature.HoleFeatures);
        }
      }
      return partDoc;
    }

    /// <summary>
    /// 将指定的PartDocument按指定的InventorTranslator进行格式转换
    /// </summary>
    /// <param name="partDoc"></param>
    /// <param name="translator"></param>
    /// <returns></returns>
    public static dynamic TranslateTo(dynamic partDoc, InventorTranslator translator, string saveAsFile)
    {
      var translatorAddIn = Application.ApplicationAddIns.ItemById[translator.ClassId] as TranslatorAddIn;
      if (translatorAddIn == null)
      {
        throw InventorException.指定的转换格式无效.Create(translator.Name);
      }
      try
      {
        var context = Application.TransientObjects.CreateTranslationContext();
        var options = Application.TransientObjects.CreateNameValueMap();
        var medium = Application.TransientObjects.CreateDataMedium();
        if (translatorAddIn.HasSaveCopyAsOptions[partDoc, context, options])
        {
          translator.SetOptions(options);
        }
        context.Type = IOMechanismEnum.kFileBrowseIOMechanism;
        medium.MediumType = MediumTypeEnum.kFileNameMedium;
        medium.FileName = saveAsFile;
        var exportRes = translatorAddIn.SaveCopyAs(partDoc, context, options, medium);
        return partDoc;
      }
      catch (Exception ex)
      {
        throw InventorException.文档格式转换失败.Create(translator.Name).SetDetail(ex.Message);
      }
    }

    /// <summary>
    /// 将零部件导出为指定的格式的文件
    /// </summary>
    /// <param name="partFile"></param>
    /// <param name="translator"></param>
    /// <param name="saveAsFile"></param>
    /// <returns></returns>
    public static dynamic TranslateTo(string partFile, InventorTranslator translator, string saveAsFile)
    {
      var partDoc = OpenDocument(partFile);
      return TranslateTo(partDoc, translator, saveAsFile);
    }
  }
}
